package training.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import training.oop.Student;

public class ReflectionDemo {
	
	
	public Object getAnObject(){
		Student student = new Student("Hari", "1") ;
		return student;
	}
	
	public void intraspectObject(Object object) throws IllegalArgumentException, IllegalAccessException{
		Class classObject = object.getClass();
		System.out.println(classObject.getName());
		Field[] fields = classObject.getFields();
		for (Field field : fields) {
			
			System.out.println("Name is :" +field.getName() +  " Type is : " + field.getType() +  "   "  + field.getModifiers());
			System.out.println("Value is :" + field.get(object));
			
		}
		
		//Let us get all fields not just public ones.
		fields = classObject.getDeclaredFields();
		for (Field field : fields) {
			
			System.out.println("Name is :" +field.getName() +  " Type is : " + field.getType() +  "   "  + field.getModifiers());
			field.setAccessible(true); //let us set accessibility to true so that we can still read private values.
			System.out.println("Value is :" + field.get(object));
			
		}
		
		Method[] methods = classObject.getMethods();
		for (Method method : methods) {
			System.out.println("Method name is :" + method.getName() +" Return type : " + method.getReturnType());
			Class[] parameterTypes = method.getParameterTypes();
			System.out.println("parameter count is :" + parameterTypes.length);
			try {
				method.invoke(object, null);
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		Constructor constructors[] = classObject.getConstructors();
		for (Constructor constructor : constructors) {
			//constructor.getParameterTypes();
			try {
				constructor.newInstance();
				
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	
	public void loadClass() throws ClassNotFoundException{
		Class classObject = Class.forName("training.oop.Singleton");
		//
		Method[] methods = classObject.getMethods();
		
		for (Method method : methods) {
			if(method.getName().contains("getInstance")){
				try {
					method.invoke(classObject, null);
					System.out.println("Singleton method is invoked");
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException {
		
		ReflectionDemo demo = new ReflectionDemo();
		Object obj = demo.getAnObject();
		//demo.intraspectObject(obj);
		demo.loadClass();

	}

}
